先延續昨天的內容,我們寫一下算平均持倉時間的程式之後用得上~
今天內容不多,因為我在台南玩XD
從目標位置推導交易的時間點:
# 定義目標位置為0的索引
df0 = tPos[tPos == 0].index
# 將目標位置序列向下移動一個位置,找出非0的索引
df1 = tPos.shift(1)
df1 = df1[df1 != 0].index
# 找出需要平倉(變為平倉狀態)的時機
bets = df0.intersection(df1) # 平倉時機
# 計算連續兩個目標位置的乘積,找出其變號(翻轉)的索引
df0 = tPos.iloc[1:] * tPos.iloc[:-1].values
bets = bets.union(df0[df0 < 0].index).sort_values() # 加入變號時機
# 確保最後一個賭注被包含在內
if tPos.index[-1] not in bets:
bets = bets.append(tPos.index[-1:]) # 加入最後一個賭注
計算平均持倉時間:
def getHoldingPeriod(tPos):
# 使用平均進場時間配對算法來推導平均持有期(以天為單位)
hp, tEntry = pd.DataFrame(columns=['dT', 'w']), 0.0
# 計算目標位置和時間的差值
pDiff = tPos.diff()
tDiff = (tPos.index - tPos.index[0]) / np.timedelta64(1, 'D')
for i in xrange(1, tPos.shape[0]):
# 如果目標位置增加或不變
if pDiff.iloc[i] * tPos.iloc[i - 1] >= 0:
if tPos.iloc[i] != 0:
tEntry = (tEntry * tPos.iloc[i - 1] + tDiff[i] * pDiff.iloc[i]) / tPos.iloc[i]
else: # 目標位置減少
# 如果目標位置發生變號(翻轉)
if tPos.iloc[i] * tPos.iloc[i - 1] < 0:
hp.loc[tPos.index[i], ['dT', 'w']] = (tDiff[i] - tEntry, abs(tPos.iloc[i - 1]))
tEntry = tDiff[i] # 重設進場時間
else:
hp.loc[tPos.index[i], ['dT', 'w']] = (tDiff[i] - tEntry, abs(pDiff.iloc[i]))
# 計算加權平均持有期
if hp['w'].sum() > 0:
hp = (hp['dT'] * hp['w']).sum() / hp['w'].sum()
else:
hp = np.nan # 如果沒有有效的權重,則設為NaN
return hp
績效統計是不考慮風險調整的收益。一些有用的績效指標像是: